package com.asen.commons.core.jdbc.handler;

import com.asen.commons.core.base.model.BaseEnumEntry;
import com.asen.commons.utils.BaseAssert;
import com.asen.commons.exception.TypeException;
import com.asen.commons.core.base.IntegerEnum;

import java.sql.*;

/**
 * IntegerEnum
 *
 * @author Gary
 * @version 1.0
 * @date 2018-11-29
 */
public class IntegerEnumHandler<E extends IntegerEnum> extends BaseTypeHandler<E> {

    private Class<E> type;
    private E[] enums;

    public IntegerEnumHandler(Class<E> type) {
        BaseAssert.notNull(type, "参数type不能为空");
        this.type = type;
        this.enums = type.getEnumConstants();
        BaseAssert.notNull(this.enums, type.getSimpleName() + "不是枚举类型");
    }

    @Override
    public int getSqlType() {
        return Types.INTEGER;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, IntegerEnum parameter)
            throws SQLException {
        ps.setInt(i, parameter.getValue());
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        int res = rs.getInt(columnName);
        if (rs.wasNull()) {
            return null;
        }
        return getValue(res);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int res = rs.getInt(columnIndex);
        if (rs.wasNull()) {
            return null;
        }
        return getValue(res);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int res = cs.getInt(columnIndex);
        if (cs.wasNull()) {
            return null;
        }
        return getValue(res);
    }

    public E getValue(int key) {
        for (E e : enums) {
            if (key == e.getValue()) {
                return e;
            }
        }
        throw new TypeException("不能转换【" + key + "】为对应枚举类型 " + type.getSimpleName());
    }

    @Override
    public String toSqlValue(Object value) {
        if (value == null) {
            return null;
        }

        if (value instanceof String) {
            if (value.toString().trim().length() == 0) {
                return null;
            }
        }

        if (value instanceof IntegerEnum) {
            return String.valueOf(((IntegerEnum) value).getValue());
        }

        if (value instanceof Integer || value instanceof String) {
            return value.toString();
        }

        if (value instanceof IntegerEnum[]) {
            StringBuilder sb = new StringBuilder(0);
            sb.append("(");
            for (IntegerEnum s : (IntegerEnum[]) value) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(s.getValue());
            }
            sb.append(")");
            return sb.toString();
        }

        if (value instanceof Integer[]) {
            return getSqlValue((String[]) value, false);
        }

        if (value instanceof String[]) {
            return getSqlValue((String[]) value, false);
        }

        return value.toString();
    }

    @Override
    public E getValue(Object value) throws Exception {
        if (value == null) {
            return null;
        }

        if (type.isAssignableFrom(value.getClass())) {
            return (E) value;
        }

        if (value instanceof Integer) {
            return getValue((int) value);
        }

        if (value instanceof String) {
            if (value.toString().trim().length() == 0) {
                return null;
            }

            return getValue(Integer.parseInt(value.toString()));
        }

        if (value instanceof BaseEnumEntry) {
            BaseEnumEntry enumEntry = (BaseEnumEntry) value;
            return getValue(Integer.parseInt(enumEntry.getValue()));
        }

        return getValue(Integer.parseInt(value.toString()));
    }
}
